﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MobileSales.Server.Database;
using MobileSales.Model.Exceptions;
using System.ServiceModel;
using MobileSales.Server.Properties;
using MobileSales.Common.Logger;
using System.ServiceModel.Web;
using MobileSales.Server.Util;

namespace MobileSales.Server.Services
{
    public abstract class ServiceBase
    {        
        #region Internal members

        internal MobileSalesEntities entities = new MobileSalesEntities();

        #endregion

        #region Raise
        protected void Raise(string message)
        {
            CLogger.LogError("ValidationException:" + message);
            if (Settings.Default.FaultContractsEnabled)
                throw new FaultException<ValidationException>(new ValidationException(message));
            else
                throw new Exception(message);
        } 
        #endregion

        #region GetParam
        protected MobileSales.Model.Params.Param GetParam(int paramId)
        {
            Param dbParam = entities.Params.Where(x => x.ParamId.Equals(paramId)).FirstOrDefault();
            if (dbParam != null)
            {
                MobileSales.Model.Params.Param result = new MobileSales.Model.Params.Param()
                {
                    Id = dbParam.ParamId,
                    DefaultValue = dbParam.DefaultValue,
                    Description = dbParam.Description,
                    ParamType = (MobileSales.Model.Params.ParamType)Enum.Parse(typeof(MobileSales.Model.Params.ParamType), dbParam.ParamType.Name),
                    FieldType = MobileSales.Model.Params.FieldTypes.GetFieldType(dbParam.FieldType),
                    IsReadOnly = dbParam.ReadOnly,
                    IsRequired = dbParam.Required,
                    MaxLength = dbParam.MaxLength,
                    DisplayName = dbParam.DisplayName,
                    Name = dbParam.Name
                };
                return result;
            }
            return null;
        }
        #endregion

        #region ValidateToken

        protected void ValidateToken()
        {
            if (Settings.Default.ValidationEnabled)
            {
                try
                {
                    string token = GetValidationToken();
                    if (token == null)
                        this.Raise("Invalid token");
                    int employeeId = entities.Employees.Where(x => x.ValidationToken.Equals(new Guid(token))).Select(x => x.EmployeeId).FirstOrDefault();
                    if (employeeId == 0)
                        this.Raise("Invalid token");
                }
                catch (Exception ex)
                {
                    CLogger.LogDebug(ex);
                    this.Raise("Invalid token");
                }
            }
        }

        protected void ValidateTokenFor(int userId)
        {
            if (Settings.Default.ValidationEnabled)
            {
                try
                {
                    string token = GetValidationToken();
                    if (token == null)
                        this.Raise("Invalid token");

                    int employeeId = entities.Employees.Where(x => x.ValidationToken.Equals(new Guid(token))).Select(x => x.EmployeeId).FirstOrDefault();
                    if (employeeId != userId)
                        this.Raise("Invalid token");
                }
                catch (Exception ex)
                {
                    CLogger.LogDebug(ex);
                    this.Raise("Invalid token");
                }
            }
        }

        protected string GetValidationToken()
        {
            string token = null;

            /* try find token in http header */
            try
            {
                token = WebOperationContext.Current.IncomingRequest.Headers.Get(Settings.Default.TokenKey);
            }
            catch { }

            /* try find token in soap envelope */
            try
            {
                token = OperationContext.Current.IncomingMessageHeaders.GetHeader<string>(Settings.Default.TokenKey, string.Empty);
            }
            catch { }

            return token;
        }

        #endregion

        #region GetEmployeeIdFromToken
        protected int GetEmployeeIdFromToken()
        {
            try
            {
                string token = this.GetValidationToken();
                int employeeId = entities.Employees.Where(x => x.ValidationToken.Equals(new Guid(token))).Select(x => x.EmployeeId).FirstOrDefault();
                if (employeeId == 0)
                    throw new Exception("Could not find employee for token");
                return employeeId;
            }
            catch (Exception ex)
            {
                CLogger.LogDebug(ex);
                throw;
            }
        } 
        #endregion

        #region NotifyEmployees
        protected void NotifyAll(ServiceType type, string methodName, object param)
        {
            IEmployeeNotifier notifier = new EmployeeNotifier(entities);
            String message = GetNotificationMessage(type, methodName, param);
            notifier.Notify(message);
        }

        public void Notify(int userId, ServiceType type, string methodName, object param)
        {
            IEmployeeNotifier notifier = new EmployeeNotifier(entities);
            String message = GetNotificationMessage(type,methodName,param);
            notifier.Notify(userId, message);
        }

        private string GetNotificationMessage(ServiceType type, string methodName, object param)
        {
            return string.Format("{0}REST.svc/{1}/{2}", type.ToString(), methodName, param.ToString());
        }
        #endregion

        #region IsBrowserAccess
        protected bool IsBrowserAccess()
        {
            bool isBrowserAcc = false;

            /* try find token in soap envelope */
            try
            {
                String token = OperationContext.Current.IncomingMessageHeaders.GetHeader<string>(Settings.Default.TokenKey, string.Empty);
                isBrowserAcc = true;
            }
            catch { }
            return isBrowserAcc;
        } 
        #endregion
        
    }
}
